/*
 * 系统项目名称：综合决策分析系统
 * 文件名：DataConfCache.java
 * 描述：
 * 版权：Copyright 2015-2020 义乌市跨境电商供应链管理有限公司-版权所有
 * 修改人：xushaobing
 * 修改时间：2015年10月19日 上午9:38:44
 * 版本号：V1.1
 */
package com.ywt.cda.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

import javax.annotation.Resource;

import org.apache.log4j.Logger;

import com.ywt.cda.dao.ConfDataDao;
import com.ywt.cda.dao.MCategoryDao;
import com.ywt.cda.dao.SCategoryDao;
import com.ywt.cda.domain.ConfCountry;
import com.ywt.cda.domain.ConfGoods;
import com.ywt.cda.domain.ConfParam;
import com.ywt.cda.domain.Coordinate;
import com.ywt.cda.domain.MCategory;
import com.ywt.cda.domain.SCategory;
import com.ywt.cda.domain.enums.ConfTable;
import com.ywt.cda.domain.enums.ParamFlag;
import com.ywt.cda.utils.BaiduMapApi;

/**
 * 配置信息缓存器 <br>
 * （功能详细描述）
 * 
 * @author 徐韶兵
 * @version V1.0
 * @see [相关类/方法]
 * @since 2015年10月19日 上午9:38:44
 */
public class ConfDataCacheService 
{
	/**
	 * 日志读取器
	 */
	private static final Logger logger = Logger.getLogger(ConfDataCacheService.class);
	/**
	 * 配置信息缓存唯一实例
	 */
	/**
	 * 配置参数数据访问层接口
	 */
	@Resource
	private ConfDataDao confDataDao;
	@Resource
	private MCategoryDao mCategoryDao;
	@Resource
	private SCategoryDao sCategoryDao;
	/**
	 * 通用参数缓存
	 */
	private Map<String, Map<String, ConfParam>> paramsMap = new HashMap<String, Map<String, ConfParam>>();
	/**
	 * 国家参数缓存
	 */
	private Map<String, ConfCountry> countryMap = new HashMap<String, ConfCountry>();
	/**
	 * 商品参数缓存
	 */
	private Map<String, ConfGoods> goodsMap = new HashMap<String, ConfGoods>();
	/**
	 * 商品参数缓存
	 */
	private Map<String,Map<String, Coordinate>> coordinateMap = new HashMap<String,Map<String, Coordinate>>();
	/**
	 * 查询成功队列
	 */
	private Queue<String> successQueue = new LinkedBlockingQueue<String>();
	/**
	 * 查询成功队列
	 */
	private Queue<Coordinate> coordinateQueue = new LinkedBlockingQueue<Coordinate>();
	/**
	 * 每个配置表最后更新时间
	 */
	private Map<ConfTable,Date> lastModifyTimeMap = new HashMap<ConfTable,Date>();
	/**
	 * 每个配置表当前记录数
	 */
	private Map<ConfTable,Integer> conutMap = new HashMap<ConfTable,Integer>();
	
	private Map<String, MCategory> mCategoryMap=new HashMap<String,MCategory>();
	
	private Map<String, SCategory> sCategoryMap=new HashMap<String,SCategory>();

	
	
	public void run()
	{
		
			try
			{
				//缓存数据检测
				while (!coordinateQueue.isEmpty())
				{
					confDataDao.insert(coordinateQueue.poll());
				}
				//数据库数据检测
				load();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				logger.error("Conf Refresh Thread occour Exception -->" + e.toString());
			}
			//每隔5秒对数据库的数据和缓存数据做同步检测
		
	}
	/**
	 * 加载通用配置参数
	 * @exception 
	 * @since 2015年12月16日 下午3:20:24
	 * @author 徐韶兵
	 */
	private void loadCommon()
	{
		// 读取通用配置参数
		logger.info("start load ConfParamBean...");
		List<ConfParam> paramsList = confDataDao
				.listParam(new HashMap<String, Object>());
		if (null != paramsList && !paramsList.isEmpty())
		{
			for (int i = 0; i < paramsList.size(); i++)
			{
				ConfParam bean = paramsList.get(i);
				Map<String, ConfParam> map = paramsMap.get(bean.getFlag());
				if (null == map)
				{
					logger.info("init ParamBean(" + bean.getFlag() + ")");
					map = new HashMap<String, ConfParam>();
					paramsMap.put(bean.getFlag(), map);
				}
				logger.debug(bean.getFlag() + " =>" + bean.toString());
				map.put(bean.getCode(), bean);
			}
		}
		logger.info("load ConfParamBean successfully!");
	}
	/**
	 * 加载国家配置参数
	 * @exception 
	 * @since 2015年12月16日 下午3:22:00
	 * @author 徐韶兵
	 */
	private void loadCountry()
	{
		// 读取国家参数数据
		logger.info("start load ConfCountryBean...");
		List<ConfCountry> countryList = confDataDao
				.listCountry(new HashMap<String, Object>());
		if (null != countryList && !countryList.isEmpty())
		{
			for (int i = 0; i < countryList.size(); i++)
			{
				ConfCountry bean = countryList.get(i);
				logger.debug(bean.getCode() + " =>" + bean.toString());
				countryMap.put(bean.getCode(), bean);
			}
		}
		logger.info("load ConfCountryBean successfully!");
	}
	/**
	 * 加载商品配置信息
	 * @exception 
	 * @since 2015年12月16日 下午3:23:33
	 * @author 徐韶兵
	 */
	private void loadGoods()
	{
		// 读取商品配置参数
		logger.info("start load ConfGoodsBean...");
		List<ConfGoods> goodsList = confDataDao
				.listGoods(new HashMap<String, Object>());
		if (null != goodsList && !goodsList.isEmpty())
		{
			for (int i = 0; i < goodsList.size(); i++)
			{
				ConfGoods bean = goodsList.get(i);
				logger.debug(bean.getName() + " =>" + bean.toString());
				goodsMap.put(bean.getName(), bean);
			}
		}
		logger.info("load ConfGoodsBean successfully!");
	}
	private void loadMcategory()
	{
		// 读取商品配置参数
		logger.info("start load Mcategory...");
		List<MCategory> mCategories =mCategoryDao.list(null, null);
		if (null != mCategories && !mCategories.isEmpty())
		{
			for (int i = 0; i < mCategories.size(); i++)
			{
				MCategory bean = mCategories.get(i);
				logger.debug(bean.getmCategoryName() + " =>" + bean.toString());
				mCategoryMap.put(bean.getmCategoryCode(), bean);
			}
		}
		logger.info("load Mcategory successfully!");
	}
	private void loadScategory()
	{
		// 读取商品配置参数
		logger.info("start load Scategory...");
		List<SCategory> sCategories =sCategoryDao.list(null, null);
		if (null != sCategories && !sCategories.isEmpty())
		{
			for (int i = 0; i < sCategories.size(); i++)
			{
				SCategory bean = sCategories.get(i);
				logger.debug(bean.getsCategoryName() + " =>" + bean.toString());
				sCategoryMap.put(bean.getsCategoryCode(), bean);
			}
		}
		logger.info("load Scategory successfully!");
	}
	/**
	 * 加载地图坐标配置信息
	 * @exception 
	 * @since 2015年12月16日 下午3:26:09
	 * @author 徐韶兵
	 */
	private void loadCoordinate()
	{
		// 读取地图配置参数
		logger.info("start load Coordinate...");
		List<Coordinate> coordinateList = confDataDao
				.listCoordinate(new HashMap<String, Object>());
		if (null != coordinateList && !coordinateList.isEmpty())
		{
			for (int i = 0; i < coordinateList.size(); i++)
			{
				Coordinate bean = coordinateList.get(i);
				Map<String, Coordinate> map = coordinateMap.get(bean
						.getCountryName());
				if (null == map)
				{
					logger.info("init Coordinate(" + bean.getCountryName()
							+ ")");
					map = new HashMap<String, Coordinate>();
					coordinateMap.put(bean.getCountryName(), map);
				}
				logger.debug(bean.getCityName() + " =>" + bean.toString());
				map.put(bean.getCityName(), bean);
			}
		}
		logger.info("load Coordinate successfully!");
	}
	/**
	 * 加载参数
	 * @exception
	 * @since 2015年10月19日 上午10:09:44
	 * @author 徐韶兵
	 */
	private void load()
	{
		for (ConfTable confTable : ConfTable.values())
		{
			// 查询配置表当前记录数
			int count = confDataDao.countRecords(confTable.getTableName());
			// 查询配置表最近修改的时间
			Date date = confDataDao.lastModifyTime(confTable.getTableName());
			//检测配置表是否存在记录数变更，或者存在时间变更
			//记录数变更说明数据库有记录新增或者删除
			//记录时间有变更说明数据库有记录新增或者修改
			if (null == conutMap.get(confTable)
					|| count != conutMap.get(confTable)
					|| null == lastModifyTimeMap.get(confTable)
					|| date.compareTo(lastModifyTimeMap.get(confTable)) != 0)
			{
				switch (confTable)
				{
				// 通用配置表
				case TB_CONF_DATA_PARAM:
					loadCommon();
					break;
				// 国家配置表
				case TB_CONF_DATA_COUNTRY:
					loadCountry();
					break;
				// 商品配置表
				case TB_CONF_DATA_GOODS:
//					loadGoods();
					break;
				case TB_M_CATEGORY:
					loadMcategory();
					break;
				case TB_S_CATEGORY:
					loadScategory();
					break;
				// 地图配置表
				case TB_CONF_DATA_MAP:
					loadCoordinate();
					break;
				default:
					break;
				}
				//将配置表最新的记录数更新
				conutMap.put(confTable, count);
				//将配置表最新的记录时间更新
				lastModifyTimeMap.put(confTable, date);
			}
		}
	}
	/**
	 * 根据国家及城市查找城市所在地图的经纬度坐标对象
	 * <br>(这里描述这个方法适用条件 – 可选)
	 * @param countryName  国家名称
	 * @param cityName 城市名称
	 * @return 城市所在地图的经纬度坐标对象
	 * @exception 
	 * @since 2015年10月29日 下午4:27:08
	 * @author 徐韶兵
	 */
	public Coordinate getCoordinate(String countryName, String cityName)
	{
		//先查看缓存是否存在城市的经纬度信息
		Map<String, Coordinate> map = coordinateMap.get(countryName);
		if (null == map)
		{
			logger.warn("Can't find Country:" + countryName);
			return null;
		}
		Coordinate coordinate = map.get(cityName);
		//缓存配置信息里面没有经纬度信息，则尝试从百度API查找
		if (null == coordinate)
		{
			logger.warn("Can't find Country " + countryName + " City:"
					+ cityName);
			String[] location = BaiduMapApi.getInstance().getChinaCoordinate(cityName);
			if (null != location && location.length == 2)
			{
				//
				coordinate = new Coordinate();
				coordinate.setCityName(cityName);
				coordinate.setCountryName(countryName);
//				coordinate.setCountryCode(countryCode);
				coordinate.setLongitude(location[0]);
				coordinate.setLatitude(location[1]);
				map.put(cityName, coordinate);
				//查找成功，为防止重复数据插入，这里看看成功列表是否含有该数据
				if (!successQueue.contains(cityName))
				{
					successQueue.offer(cityName);
					logger.info("在百度地图API找到城市" + cityName
							+ "的经纬度坐标数据成功!");
					coordinateQueue.add(coordinate);
				}
				return coordinate;
			}
			return null;
		}
		return coordinate;
	}
	
	/**
	 * 获取参数名称
	 * <br>(这里描述这个方法适用条件 – 可选)
	 * @param paramFlag 参数类型
	 * @param code 参数编码
	 * @return 参数中文名称
	 * @exception 
	 * @since 2015年10月29日 下午4:27:08
	 * @author 徐韶兵
	 */
	public String getName(ParamFlag paramFlag, String code)
	{
		Map<String, ConfParam> map = paramsMap.get(paramFlag.getFlag());
		if (null == map)
		{
			logger.warn("Can't find ParamFlag:" + paramFlag.getFlag());
			return null;
		}
		ConfParam confParam = map.get(code);
		if (null == confParam)
		{
			logger.warn("Can't find ParamFlag Code:" + code);
			return null;
		}
		return confParam.getName();
	}
	public Map<String, ConfParam> getMap(ParamFlag paramFlag)
	{
		Map<String, ConfParam> map = paramsMap.get(paramFlag.getFlag());
		if (null == map)
		{
			logger.warn("Can't find ParamFlag:" + paramFlag.getFlag());
			return null;
		}
		
		return map;
	}
	/**
	 * 获取国家配置信息
	 * <br>(这里描述这个方法适用条件 – 可选)
	 * @param countryCode 国家编码
	 * @return 国家配置信息
	 * @exception 
	 * @since 2015年10月29日 下午6:01:44
	 * @author 徐韶兵
	 */
	public ConfCountry getCountry(String countryCode)
	{
		ConfCountry confCountry = countryMap.get(countryCode);
		if (null == confCountry)
		{
			logger.warn("the Country " + countryCode
					+ " 's Mark City has not configured!");
			return null;
		}
		return confCountry;
	}

	public Map<String, Map<String, ConfParam>> getParamsMap()
	{
		return paramsMap;
	}
	public Map<String, MCategory> getmCategoryMap() {
		return mCategoryMap;
	}
	public void setmCategoryMap(Map<String, MCategory> mCategoryMap) {
		this.mCategoryMap = mCategoryMap;
	}
	public Map<String, SCategory> getsCategoryMap() {
		return sCategoryMap;
	}
	public void setsCategoryMap(Map<String, SCategory> sCategoryMap) {
		this.sCategoryMap = sCategoryMap;
	}
	public void setParamsMap(Map<String, Map<String, ConfParam>> paramsMap) {
		this.paramsMap = paramsMap;
	}
	public  Map<String, ConfCountry>  getCountryMap() {
		return countryMap;
	}
	
	
	

}
